﻿using Model;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace AlarmClock.BLL
{
    /// <summary>
    /// 百度天气API
    /// </summary>
    public class BaiduWeatherWebApi
    {
        #region 向用户公布的接口
        public static Root AllWeatherInfo { get; set; }

        /// <summary>
        /// 向用户公布的天气接口:查询所有天气信息
        /// </summary>
        /// <returns></returns>
        public static Root GetAllWeather(string city = "")
        {
            string jsonStr = "";
            if (string.IsNullOrEmpty(city))
            {
                jsonStr = Location != null ? GetBaiduWeather(Location["区"]) : GetBaiduWeather("番禺");
            }
            else
            {
                jsonStr = GetBaiduWeather(city);
            }
            if (jsonStr == null) return AllWeatherInfo;//没有百度地图ak，该功能不开放

            return AllWeatherInfo = JsonConvert.DeserializeObject<Root>(jsonStr);        
        }

        /// <summary>
        /// 向用户公布的天气接口：查询主要天气信息
        /// </summary>
        /// <param name="City"></param>
        /// <returns></returns>
        public async static Task<string> GetMainWeather(string city = "")
        {
            Root AllWeatherInfo = null;
            await Task.Run(new Action(() => {
                if (string.IsNullOrEmpty(city))
                {
                    AllWeatherInfo = GetAllWeather();
                }
                else
                {
                    AllWeatherInfo = GetAllWeather(city);
                }
            }));
            if (AllWeatherInfo == null || AllWeatherInfo.result == null) return "查询结果为空，请检查网络或者软件配置";
            string cityName = AllWeatherInfo.result.location.name;
            string temprate = AllWeatherInfo.result.now.temp.ToString();
            string weather=AllWeatherInfo.result.now.text;
            return $"{cityName}  {temprate}℃ {weather}";
        }

        /// <summary>
        /// 向用户公布的接口：查询所有支持查询的城市列表
        /// </summary>
        /// <returns></returns>
        public static string[] GetAllCities()
        {
            return CityID_Dic.Keys.ToArray();
        }


        #endregion

        #region 私有方法：获取本机IP、所在城市名，区县的行政区划编码,访问百度天气API

        /// <summary>
        /// 获取页面html
        /// </summary>
        /// <param name="url">请求的地址</param>
        /// <param name="encoding">编码方式</param>
        /// <returns></returns>
        public static string GetHtml(string url, string encoding)
        {
            string pageHtml = string.Empty;
            try
            {
                using (WebClient MyWebClient = new WebClient())
                {
                    Encoding encode = Encoding.GetEncoding(encoding);
                    MyWebClient.Headers.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.84 Safari/537.36");
                    MyWebClient.Credentials = CredentialCache.DefaultCredentials;//获取或设置用于向Internet资源的请求进行身份验证的网络凭据
                    Byte[] pageData = MyWebClient.DownloadData(url); //从指定网站下载数据
                    pageHtml = encode.GetString(pageData);
                }
            }
            catch (Exception)
            {
                return "访问 " + url + " 失败，请检查网络配置";
            }
            return pageHtml;
        }

        /// <summary>
        /// 从html中通过正则找到ipv4信息
        /// </summary>
        /// <param name="pageHtml"></param>
        /// <returns></returns>
        public static string GetGlobalIP()
        {
            string pageHtml = GetHtml("http://www.net.cn/static/customercare/yourip.asp", "gbk");
            //验证ipv4地址
            string reg = @"(?:(?:(25[0-5])|(2[0-4]\d)|((1\d{2})|([1-9]?\d)))\.){3}(?:(25[0-5])|(2[0-4]\d)|((1\d{2})|([1-9]?\d)))";
            string ip = "none";
            Match m = Regex.Match(pageHtml, reg);
            if (m.Success)
            {
                ip = m.Value;
            }
            Console.WriteLine("公网ip：" + ip);
            return ip;
        }

        private static Dictionary<string, string> Location => GetLocation();

        /// <summary>
        /// 根据IP地址获取城市信息
        /// </summary>
        /// <returns></returns>

        private static Dictionary<string, string> GetLocation()
        {
            try
            {
                //string ip = "112.17.30.75";
                string ip = GetGlobalIP();
                string html = GetHtml("https://www.ip138.com/iplookup.asp?ip=" + ip + "&action=2", "gb2312");
                //Console.WriteLine(html);
                string pre = "var ip_result = {\"ASN归属地\":\"";
                int pos = html.IndexOf(pre);
                html = html.Substring(pos + pre.Length);
                html = html.Substring(0, html.IndexOf('"'));
                // 变为"浙江省杭州市  移动 "
                string[] res = html.Split(new char[] { '省', '市', '区', ' ' }, StringSplitOptions.RemoveEmptyEntries);

                var M = new Dictionary<string, string>();
                M["省"] = res[0];
                M["市"] = res[1];
                M["区"] = res[2];
                M["运营商"] = res[3];

                return M;
            }
            catch (Exception)
            {
                return null;
            }

        }


        private static Dictionary<string, string> CityID_Dic
            => GetDistrict_idOfCity(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"Resourse\weatherInfo.txt"));

        private static Dictionary<string, string> GetDistrict_idOfCity(string Path)
        {
            Dictionary<string, string> res = new Dictionary<string, string>();
            using (FileStream fs = new FileStream(Path, FileMode.Open))
            {
                using (StreamReader sr = new StreamReader(fs))
                {
                    string line = "";
                    while ((line = sr.ReadLine()) != null)
                    {
                        string[] data = line.Split();

                        if (res.ContainsKey(data[1]))
                            res[data[1]] = data[0];
                        else res.Add(data[1], data[0]);
                    }
                }
            }
            return res;
        }

        /// <summary>
        /// 调用百度API获取天气预报
        /// </summary>
        /// <param name="cityName">城市名称</param>
        /// <returns></returns>
        private static string GetBaiduWeather(string cityName)
        {
            if (CityID_Dic == null)
            {
                return null;
            }

            List<string> suffixs = new List<string>() { "村", "乡", "镇", "县", "区", "市", "省" };
            suffixs.ForEach(s => { cityName = cityName.Replace(s, ""); });

            string district_id = GetDicValue(CityID_Dic, cityName, suffixs);
            string result = string.Empty;

            try
            {   //能找到这里的说明你对webAPI是感兴趣的，记得去百度地图官网申请个开发者密钥ak,放到App.config里;
                var listAk = ConfigurationManager.AppSettings.Get("BaiduWeatherAPI_AK").Split(',');
                if (string.IsNullOrEmpty(district_id)) return result;
                foreach (var ak in listAk)
                {
                    ///【district_id】： 区县的行政区划编码，和location二选一
                    ///【data_type】： 请求数据类型。数据类型有：now/fc/index/alert/fc_hour/all，控制返回内容
                    ///【ak】： 开发者密钥，可在API控制台申请获得
                    string str = "https://api.map.baidu.com/weather/v1/?district_id="
                        + district_id + "&data_type=all&ak="
                        + ak;
                    var request = (HttpWebRequest)WebRequest.Create(str);
                    var response = (HttpWebResponse)request.GetResponse();
                    Stream stream = response.GetResponseStream();
                    if (stream != null)
                    {
                        result = new StreamReader(stream,Encoding.UTF8).ReadToEnd();
                        if (result.IndexOf("Error", System.StringComparison.Ordinal) < 0)
                        {
                            response.Close();
                            break;
                        }
                    }
                }
            }
            catch (Exception)
            {
                return result;
            }
            return result;
        }

        /// <summary>
        /// 后追加字符串查询Dic
        /// </summary>
        /// <param name="dic"></param>
        /// <param name="key">原始key</param>
        /// <param name="appends">附加字符串继续去查dictionary</param>
        /// <returns></returns>
        private static string GetDicValue(Dictionary<string, string> dic, string key, List<string> suffixs)
        {
            if (dic.ContainsKey(key))
            {
                return dic[key];
            }

            string result = "";
            int idx = 0;
            while (idx < suffixs.Count)
            {
                string appendKey = key + suffixs[idx++];
                if (dic.ContainsKey(appendKey))
                {
                    return dic[appendKey];
                }
            }
            return result;
        }

        #endregion

    }

}
